iT邦幫忙

2024 iThome 鐵人賽

DAY 5
0
Modern Web

關於寫react 那二三事系列 第 5

Day5 關於primereact sidebar 跟panelmenu

  • 分享至 

  • xImage
  •  

今天增加側邊導航列,
這也算是普遍網頁需要的功能,
那麼就開始吧!

首先,要知道自己需要甚麼,
一般網頁,不太需要太多複雜機制?
或者 功能相當複雜的網頁(資料需要交錯使用之類的)?

如果沒特別複雜,就用個react-router-dom 解決導航問題,
但功能複雜可以考慮redux,
以及有無實際router需要是否要再多安裝react-router-dom。

這邊只是單純demo展示,所以僅使用react-router-dom,
(當然你想用useEffect自己增加事件處理邏輯...也是可以,但我不想)
後面元件突然想弄點特別的再斟酌安裝redux,
後面也會提醒一下如果導引使用純redux後,primereact元件可能會有甚麼問題。

npm i react-router-dom --save

然後調整一下頁面,給sidebar留一個位子,旁邊的內文加點RWD設計,
老實說,RWD對我來說一直是個很抽象的概念,但秉持使用方好點,
畫面一直維持滿版的就可以了吧(?
於是我這不專業的門外人就不多說甚麼太專業的話了

.sidebar {
    width: 200px;
}
.content {
    display: flex;
    margin-left: 200px;
}

再來添加router

index.tsx

import React from 'react';
import ReactDOM from 'react-dom/client';
import './styles.scss';
import 'primereact/resources/themes/arya-green/theme.css';
import 'primereact/resources/primereact.css';
import 'primeicons/primeicons.css'
import App from './App';
import reportWebVitals from './reportWebVitals';
import {BrowserRouter} from 'react-router-dom';
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

reportWebVitals();

※有些人會把Routers(Switch)跟 Router也寫在這裡,但我個人是喜歡寫成這樣,
我個人覺得沒有對錯(也可能我這是壞習慣,請大神們不吝指教)全憑個人

App.tsx

import React from 'react';
import { Sidebar } from 'primereact/sidebar';
import ButtonCompnent from './components/Buttons';
import FormsCompnent from './components/Forms';
import {Route, Routes, useNavigate, useLocation } from 'react-router-dom';

function App() {
  const navigate = useNavigate();
  const location = useLocation();
  return (
    <div className="App">
      <Sidebar
        className="sidebar"
        visible={true}
        position="left"
        onHide={() => { }}
        showCloseIcon={false}
        modal={false}
        dismissable={false}
        header="PrimeReact二三事"
      >
      </Sidebar>
      <div className="content">
          <Routes>
            <Route path='/buttons' Component={ButtonCompnent} />
            <Route path='/forms' Component={FormsCompnent} />
          </Routes>
      </div>
    </div>
  );
}
export default App;

這版Sidebar預設是隱藏,當然你可以做一個RWD判定,如果視窗小於多少就隱藏之類的,
這部分就自由發揮,我讓她固定在左側,然後onHide我不寫出來就紅,所以寫一個空的,
在來看看她的右上角有個X的icon,本來就不打算能關就把它隱藏吧,
(利用showCloseIcon 將它隱藏),
如果在modal未設定情況下run start,就會發現content區域有一層灰灰的遮罩,
如果沒有需要,切記設定為false

※既然關閉了遮罩(modal),dismissable要記得關掉,
不然content區域在用到CheckBox之類的元件時,就會有驚天地泣鬼神的事情,
甚麼GROUP 選第一個之後,第二個沒辦法點之類的狗血事

再來添加PanelMenu

import { PanelMenu } from 'primereact/panelmenu';
import { MenuItem, MenuItemCommandEvent } from 'primereact/menuitem'; //ts定義引用

先來設定項目的部分

  const [pitem,setPItem] =useState<string>(location.pathname); 
  const items: MenuItem[] = [
    {
      label: 'Button',
      data: '/buttons',
      icon:'pi pi-box',
      className:pitem==='/buttons'?'p-highlight':'',
      command: (e: MenuItemCommandEvent) =>{
        setPItem(e.item.data);
        navigate(e.item.data);
      } 
    },
    {
      label: 'Forms',
      data: '/forms',
      icon:'pi pi-receipt',
      className:pitem==='/forms'?'p-highlight':'',
      command: (e: MenuItemCommandEvent) =>{
        setPItem(e.item.data);
        navigate(e.item.data);
      } 
    }
  ]

然後在sidebar內使用它

  <Sidebar
    className="sidebar"
    visible={true}
    position="left"
    onHide={() => {}}
    showCloseIcon={false}
    modal={false}
    dismissable={true}
    header="PrimeReact二三事"
  >
    <PanelMenu model={items} />
  </Sidebar>

再來因為個人覺得原始樣式不好看,隨變魔改一下它的樣式,
當然你也可以用template整個大改,但我覺得不是這次主題就不大動干戈

.sidebar {
    width: 200px;
    .p-sidebar-header {
        font-size: 20px;
        font-weight: bold;
    }
    .p-sidebar-content {
        padding: 0;
        .p-panelmenu {
            .p-panelmenu-panel {
                &.p-highlight {
                    .p-panelmenu-header-content {
                        background-color: #303030;
                    }
                }
                &:hover{
                    .p-panelmenu-header-content {
                        background-color: #424242;
                    }  
                }
                .p-panelmenu-header {
                    .p-panelmenu-header-content {
                        border: 0;
                        border-radius: 0;
                    }
                }
            }
        }
    }
}

好了,一個簡單的導覽列就完成啦,讓我們來看看成果

https://ithelp.ithome.com.tw/upload/images/20240805/20168266Yc2I4jmpIy.jpg

勉強還算可以吧?
總之頂用!
明天就可以開始繼續進行預計要動的Forms囉~

[題外話]
如果我再設定panelmenu切換頁面邏輯時,單純使用redux dispatch 當前item 點及項目時,
要特別注意,建議是在item內增加 url:'#'設定...

為什麼呢?
因為如果不加,會發現你在切item的時候,
其它能展開的PrimeReact元件(例如DropDown Calendar...),
收、不、起、乃
只好硬著頭皮去硬嗑它元件邏輯,發現...
好樣的!!!
在沒有url情況下,
它會阻止事件冒泡,冒不到外層就沒辦法觸發收合事件,
但也不能說是bug,因為也許有些人就是不希望收起來阿~~~

好了,今天就到此為止啦~~
明天見!


上一篇
Day4 primereact 的Button
下一篇
Day6 關於primereact的Forms (上)
系列文
關於寫react 那二三事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言